import { Routes } from "./Routes"
import { BaseComponents } from '../common/base/BaseComponent';
import GameConst from '../common/const/GameConst';
import LFUCache from "../common/lfu/LFUCache";
import RouteStack from "./RouteStack";
import { BaseState } from "../common/base/BaseState";
import { BaseLogic } from "../common/base/BaseLogic";

export default class Router {

    static pageStack: RouteStack = new RouteStack()
    static pageCache: LFUCache<string, cc.Asset> = new LFUCache<string, cc.Asset>(1, 0)

    static to(pageName: string): void {
        this.toWithArgs(pageName, {})
    }

    static async toWithArgs(pageName: string, args: object) {
        const route = Routes.routes.find(v => v.name === pageName)
        if (route) {
            let page = this.existPageNode(route.name)
            if(!page) {
                let res = this.pageCache.get(route.name)
                if(res) {
                    page = cc.instantiate(res)
                    page.name = route.name
                }
            }
            
            //如果缓存中有实例化的界面
            if (page) {
                this.initPage(route, page)
                // cc.find("Canvas").addChild(page)
                page.zIndex = this.pageStack.length() + 1
                page.active = true
                cc.game.emit(GameConst.Event.SCENE_ENABLE, args)
                this.pageStack.push(page)
            } else {
                cc.resources.load(route.path, cc.Prefab, async (e, res: cc.Prefab) => {
                    let page = cc.instantiate(res)
                    page.name = route.name
                    page.zIndex = this.pageStack.length() + 1
                    this.pageCache.put(route.name, res)
                    this.initPage(route, page)
                    cc.find("Canvas").addChild(page)
                    cc.game.emit(GameConst.Event.SCENE_ENABLE, args)
                    res.addRef();
                    this.pageStack.push(page)
                })
            }

        } else {
            cc.log("未找到页面")
        }
    }

    static back() {
        let page = this.pageStack.pop()
        page.active = false
        cc.game.emit(GameConst.Event.SCENE_ENABLE, {})
    }

    private static existPageNode(name: String): cc.Node {
        return cc.find("Canvas/" + name)
    }

    private static initPage(route, page: cc.Node) {
        const script: BaseComponents<BaseState,BaseLogic<BaseState>> = page.getComponent(route.binding)
        route.logic.setState(route.state)
        script.init(route.logic, route.state)
    }
}